// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#include <pollux/testing/functions/prestosql/function_base_test.h>

using namespace kumo::pollux;
using namespace kumo::pollux::test;

class NotTest : public functions::test::FunctionBaseTest {};

TEST_F(NotTest, noNulls) {
  constexpr vector_size_t size = 1'000;

  // All true. Flat encoding.
  auto allTrue = make_flat_vector<bool>(size, [](auto /*row*/) { return true; });
  auto result =
      evaluate<SimpleVector<bool>>("not(c0)", make_row_vector({allTrue}));
  assertEqualVectors(make_constant(false, size), result);

  // All true. Constant encoding.
  result = evaluate<SimpleVector<bool>>(
      "not(c0)", make_row_vector({make_constant(true, size)}));
  assertEqualVectors(make_constant(false, size), result);

  // All false. Flat encoding.
  auto allFalse =
      make_flat_vector<bool>(size, [](auto /*row*/) { return false; });
  result = evaluate<SimpleVector<bool>>("not(c0)", make_row_vector({allFalse}));
  assertEqualVectors(make_constant(true, size), result);

  // All false. Constant encoding.
  result = evaluate<SimpleVector<bool>>(
      "not(c0)", make_row_vector({make_constant(false, size)}));
  assertEqualVectors(make_constant(true, size), result);

  // False in odd positions: True, False, True, False,... .
  auto oddFalse =
      make_flat_vector<bool>(size, [](auto row) { return row % 2 == 0; });
  result = evaluate<SimpleVector<bool>>("not(c0)", make_row_vector({oddFalse}));
  for (int i = 0; i < size; ++i) {
    EXPECT_EQ(result->value_at(i), i % 2 == 1) << "at " << i;
  }
}

TEST_F(NotTest, someNulls) {
  constexpr vector_size_t size = 1'000;

  // False in even positions: False, True, False, True, .....; with some nulls.
  auto evenFalse = make_flat_vector<bool>(
      size, [](auto row) { return row % 2 == 1; }, null_every(7));
  auto result =
      evaluate<SimpleVector<bool>>("not(c0)", make_row_vector({evenFalse}));

  auto expectedResult = make_flat_vector<bool>(
      size, [](auto row) { return row % 2 == 0; }, null_every(7));
  assertEqualVectors(expectedResult, result);
}
